#pragma once

#include <sys_def.h>

// 缓冲区，元素个数为2的幂，且不超过256。该结构体之后应当紧跟缓冲区数组。
typedef struct {
	u8_s out_index;
	u8_s in_index;
	u8_s buffer_size;
	u8_s buffer_a[0];
} fifo8_v;

// 缓冲区，元素个数为2的幂，且不超过65536。该结构体之后应当紧跟缓冲区数组。
typedef struct {
	u16_s out_index;
	u16_s in_index;
	u16_s buffer_size;
	u8_s buffer_a[0];
} fifo16_v;

// 初始化fifo8缓冲区（给定len_2_power）
static inline void fifo8_init(fifo8_v* fifo_p, u32_s len_2_power) {
	fifo_p->out_index = 0;
	fifo_p->in_index = 0;
	fifo_p->buffer_size = 1 << len_2_power;
}

// 初始化fifo16缓冲区（给定len_2_power）
static inline void fifo16_init(fifo16_v* fifo_p, u32_s len_2_power) {
	fifo_p->out_index = 0;
	fifo_p->in_index = 0;
	fifo_p->buffer_size = 1 << len_2_power;
}

// 获取索引的下一个位置，其中buffer_size必须为2的幂。
static inline u32_s fifo_next_index(u32_s index, u32_s buffer_size) {
	return (index + 1) & (buffer_size - 1);
}

// 判断fifo8缓冲区是否有数据，若为空，返回0，否则返回非0值（具体值不保证）。
static inline u32_s fifo8_has_data(const fifo8_v* fifo_p) {
	return (fifo_p->out_index != fifo_p->in_index);
}

// 判断fifo16缓冲区是否有数据，若为空，返回0，否则返回非0值（具体值不保证）。
static inline u32_s fifo16_has_data(const fifo16_v* fifo_p) {
	return (fifo_p->out_index != fifo_p->in_index);
}

// 判断fifo8缓冲区是否已满，若未满，返回0，否则返回非0值（具体值不保证）。
static inline u32_s fifo8_is_full(const fifo8_v* fifo_p) {
	u32_s out_index = fifo_p->out_index;
	u32_s in_index = fifo_p->in_index;
	u32_s size = fifo_p->buffer_size;
	u32_s next_in_index = fifo_next_index(in_index, size);
	return (next_in_index == out_index);
}

// 判断fifo16缓冲区是否已满，若未满，返回0，否则返回非0值（具体值不保证）。
static inline u32_s fifo16_is_full(const fifo16_v* fifo_p) {
	u32_s out_index = fifo_p->out_index;
	u32_s in_index = fifo_p->in_index;
	u32_s size = fifo_p->buffer_size;
	u32_s next_in_index = fifo_next_index(in_index, size);
	return (next_in_index == out_index);
}

// 向fifo8缓冲区写入一个字节，参数仅低8位有效。
static inline void fifo8_in_byte(fifo8_v* fifo_p, u32_s byte) {
	u32_s prev_in_index = fifo_p->in_index;
	u32_s size = fifo_p->buffer_size;
	fifo_p->in_index = fifo_next_index(prev_in_index, size);
	fifo_p->buffer_a[prev_in_index] = byte;
}

// 向fifo16缓冲区写入一个字节，参数仅低8位有效。
static inline void fifo16_in_byte(fifo16_v* fifo_p, u32_s byte) {
	u32_s prev_in_index = fifo_p->in_index;
	u32_s size = fifo_p->buffer_size;
	fifo_p->in_index = fifo_next_index(prev_in_index, size);
	fifo_p->buffer_a[prev_in_index] = byte;
}

// 从fifo8缓冲区读出一个字节，返回值仅低8位有效。
static inline u32_s fifo8_out_byte(fifo8_v* fifo_p) {
	u32_s prev_out_index = fifo_p->out_index;
	u32_s byte = fifo_p->buffer_a[prev_out_index];
	u32_s size = fifo_p->buffer_size;
	fifo_p->out_index = fifo_next_index(prev_out_index, size);
	return byte;
}

// 从fifo16缓冲区读出一个字节，返回值仅低8位有效。
static inline u32_s fifo16_out_byte(fifo16_v* fifo_p) {
	u32_s prev_out_index = fifo_p->out_index;
	u32_s byte = fifo_p->buffer_a[prev_out_index];
	u32_s size = fifo_p->buffer_size;
	fifo_p->out_index = fifo_next_index(prev_out_index, size);
	return byte;
}
